#[allow(unused)]
// fork/join
// 单线程异步io
use std::thread;
use std::sync::{mpsc ,Arc, Mutex};


///线程池结构体
///
///workers: 线程池单元
///sender: 任务通道
///
///ThreadPool -> 发送端
///worker -> 接受端
///
pub struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

// 存放发送的闭包
// struct -> type
// Job:
// 有着execute 接受到的闭包类型的trait对象的别名
type Job = Box<dyn FnOnce() + Send + 'static>;

impl ThreadPool {
    /// 创建线程池
    ///
    /// 线程池中线程数量
    ///
    /// # Panics
    ///
    /// 'new' 函数在 size 为 0 时候 会 panic
    pub fn new(size: usize) -> Self {
        // 验证线程池数量
        assert!(size > 0);
        // Vec::with_capacity 为vector 预分配空间
        let mut workers = Vec::with_capacity(size);

        let (sender, receiver) = mpsc::channel();
        // rust 通道 --- 多个发送者 单个接受者
        // 多个线程共享所有权并允许线程修改其值
        // Arc 使多个worker 接受端
        // Mutex 确保一次只有一个worker接收端能收到一个任务
        let receiver = Arc::new(Mutex::new(receiver));

        // 填充预线程
        for id in 0..size {
            // 增加receiver 的引用计数
            workers.push(Worker::new(id, Arc::clone(&receiver)));
        }
        // 返回的Self实例
        ThreadPool { workers, sender, }
    }
    ///获取一个闭包参数
    ///参数类型有: Fn, FnMut, FnOnce
    ///Fn: 引用可共享, FnMut: 独占引用, FnOnce: 独占所有权
    ///类thread::spawn 中 bound 为
    ///
    ///pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    ///where
    /// !* F: FnOnce() -> T + Send + 'static,
    ///    T: Send + 'static
    ///
    /// f: 一个闭包
    pub fn execute<F>(&self, f: F) 
        where
            F: FnOnce() + Send + 'static
    {
        let job = Box::new(f);
        self.sender.send(Message::NewJob(job)).unwrap();
    }
}

impl Drop for ThreadPool {
    ///释放方法
    ///当线程池被丢弃时候
    ///应该join所有线程以确保已经完成所有任务
    fn drop(&mut self) { // &mut -> worker能修改
        println!("Sending terminate message to all workers");
        
        // 分开循环: 
        // 发送的终止信息不一定有当前迭代的worker接受 ->> 死锁

        // 给每个worker发送线程退出消息 | 无用循环 _ 对应workers数量
        for _ in &mut self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }
        println!("Shutting down all workers.");
        
        // join 要获得其参数的所有权
        // 而&mut 只有 可变借用
        // --> 将thread 移出其所有权worker实例 
        for worker in &mut self.workers {
            println!("Shutting down worker {}", worker.id);

            // 将thread 移出拥有所有权的worker | Option::take() | if let 解构
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

///单独线程单元
///私有
///id: 线程单元id
///thread: 线程单元的 任务 (thread::JoinHandle<()> 实例)
struct Worker {
    id: usize,
    thread: Option<thread::JoinHandle<()>>,
}

/// 用于修改线程监听
enum Message {
    NewJob(Job), // 线程要运行的job
    Terminate, // 线程退出标志
}

impl Worker {
    ///创建Worker
    ///id
    ///thread: 空闭包
    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
        // worker 实例 一直loop循环 等待任务
        let thread = thread::spawn(move || {
            // 不用while let -> while表达式中的值在整个块中一直处于同一个作用域, 
            // receiver 的lock不会 释放
            // 没有公有unlock方法
            loop {
                let message = receiver.lock().unwrap().recv().unwrap();
                match message {
                    Message::NewJob(job) => {
                        println!("Worker {} got a job; excuting...", id);
                        job();
                    },
                    Message::Terminate => {
                        println!("Worker {} was told to terminate", id);
                        break;
                    }
                }

            }
        });
        Worker { id, thread: Some(thread) }
    }
}

